package com.topvision.rxjava_retrofit;

import android.os.Bundle;
import android.os.SystemClock;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.TextView;

import com.topvision.rxjava_retrofit.retrofit.MovieService;
import com.topvision.rxjava_retrofit.retrofit.RetrofitManager;
import com.topvision.rxjava_retrofit.retrofit.module.TestBean;

import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import io.reactivex.Flowable;
import io.reactivex.Observable;
import io.reactivex.ObservableEmitter;
import io.reactivex.ObservableOnSubscribe;
import io.reactivex.ObservableSource;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
import io.reactivex.functions.BiFunction;
import io.reactivex.functions.Consumer;
import io.reactivex.functions.Function;
import io.reactivex.schedulers.Schedulers;

public class HomeActivity extends AppCompatActivity {

    private TextView mTvResult;
    private Disposable mDisposable;

    private TextView mTextView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_home);
        mTvResult = (TextView) findViewById(R.id.tv_result);
    }


    /**
     * Map操作符：操作原始数据，转化数据类型
     * 使用：网络数据解析
     */
    public void map(View view) {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                SystemClock.sleep(1000);
                e.onNext("我是被观察者发送的数据");
            }
        }).map(new Function<String, StringBuffer>() {
            @Override
            public StringBuffer apply(String s) throws Exception {
                SystemClock.sleep(1000);
                return new StringBuffer(s).append("\n").append("我是Map操作转化的数据");
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<StringBuffer>() {
            @Override
            public void accept(StringBuffer buffer) throws Exception {
                mTvResult.setText(buffer.toString());
            }
        }, new Consumer<Throwable>() {
            @Override
            public void accept(Throwable throwable) throws Exception {
                mTvResult.setText(throwable.getMessage());
            }
        });
    }

    /**
     * Concat 优先操作前者事件，前者事件必须completed才会操作后者事件
     * 使用：先读取缓存再通过网络请求获取数据
     * 注意：两者事件的泛型（数据类型）必须一致
     */
    public void concat(View view) {
        Observable<String> firstObservable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("我是firstObservable,2S前发送的数据");
                SystemClock.sleep(2000);
                e.onNext("我是firstObservable,发送最后一条数据");
                e.onComplete();
            }
        });
        Observable<String> secondObservable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                SystemClock.sleep(2000);
                e.onNext("我是secondObservable,发送一条数据");
            }
        });
        Observable.concat(firstObservable, secondObservable)
                .subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<String>() {
                    @Override
                    public void accept(String s) throws Exception {
                        mTvResult.setText(s);
                    }
                }, new Consumer<Throwable>() {
                    @Override
                    public void accept(Throwable throwable) throws Exception {

                    }
                });

        // 正常操作会一一执行
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                e.onNext("1");
                System.out.println(1);
                e.onNext("2");
                System.out.println(2);
                e.onNext("3");
                System.out.println(3);
            }
        }).subscribe(new Consumer<String>() {
            @Override
            public void accept(String s) throws Exception {
                System.out.println("accept:" + s);
            }
        });
    }

    /**
     * flatMap操作符：先进行某个操作获取数据，再根据前者的操作结果进行后续操作
     * 浅显理解：跟Map的区别在与返回值，Map返回转化后对象，FlatMap返回Observable携带对象
     * 使用：多个网络请求依次依赖
     */
    public void flatmap(View view) {
        Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                SystemClock.sleep(1000);
                e.onNext("我是被观察者发送的数据");
            }
        }).flatMap(new Function<String, ObservableSource<StringBuffer>>() {
            @Override
            public ObservableSource<StringBuffer> apply(final String s) throws Exception {
                return Observable.create(new ObservableOnSubscribe<StringBuffer>() {
                    @Override
                    public void subscribe(ObservableEmitter<StringBuffer> e) throws Exception {
                        e.onNext(new StringBuffer(s).append("\n").append("我是FlatMap操作的数据"));
                    }
                });
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<StringBuffer>() {
            @Override
            public void accept(StringBuffer buffer) throws Exception {
                mTvResult.setText(buffer.toString());
            }
        });
    }

    /**
     * Zip操作符：合并2个事件的结果，输出另一个结果（会进行等待，2者均执行完毕再进行操作）
     * 使用：多个接口数据共同更新 UI
     */
    public void zip(View view) {
        Observable<String> firstObservable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                SystemClock.sleep(1000);
                e.onNext("我是firstObservable,发送数据");
            }
        });
        Observable<String> secondObservable = Observable.create(new ObservableOnSubscribe<String>() {
            @Override
            public void subscribe(ObservableEmitter<String> e) throws Exception {
                SystemClock.sleep(2000);
                e.onNext("我是secondObservable,发送数据");
            }
        });
        Observable.zip(firstObservable, secondObservable, new BiFunction<String, String, StringBuffer>() {
            @Override
            public StringBuffer apply(String s, String s2) throws Exception {
                return new StringBuffer(s).append("\n").append(s2).append("\n").append("我是Zip操作符,操作数据");
            }
        }).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe(new Consumer<StringBuffer>() {
            @Override
            public void accept(StringBuffer buffer) throws Exception {
                mTvResult.setText(buffer.toString());
            }
        });
    }

    /**
     * interval操作符：轮询操作
     * 使用：心跳间隔任务
     */
    public void interval(View view) {
        mDisposable = Flowable.interval(1, TimeUnit.SECONDS)
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<Long>() {
                    @Override
                    public void accept(Long aLong) throws Exception {
                        if (aLong == 10 && mDisposable != null) {
                            mDisposable.dispose();
                        }
                        mTvResult.setText("倒计时：" + (10 - aLong));
                    }
                });
        // 记得Activity销毁时，取消任务
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (mDisposable != null) {
            mDisposable.dispose();
        }

    }

    public void request(View view) {
//        normalRequest();
        rxRequest();
    }

    private void normalRequest() {
        /*
        MovieService movieService = RetrofitManager.getInstance().create(MovieService.class);
        Call<MovieBean> call = movieService.getTop250(0, 10);
        call.enqueue(new Callback<MovieBean>() {
            @Override
            public void onResponse(Call<MovieBean> call, Response<MovieBean> response) {
                mTextView.setText(response.body().toString());
            }

            @Override
            public void onFailure(Call<MovieBean> call, Throwable t) {
                mTextView.setText(t.getMessage());
            }
        });
        */
    }

    private void rxRequest() {
//        MovieService movieService = RetrofitManager.getInstance().create(MovieService.class);
//        movieService.getTop250(0, 10)
//                .subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(new Consumer<MovieBean>() {
//                    @Override
//                    public void accept(@NonNull MovieBean movieBean) throws Exception {
//                        mTextView.setText(movieBean.toString());
//                    }
//                });

//        WanAndroidApis wanAndroidApis = RetrofitManager.getInstance().create(WanAndroidApis.class);
//        wanAndroidApis.getNavigationData()
//                .subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(new Consumer<NavigationResponse>() {
//                    @Override
//                    public void accept(@NonNull NavigationResponse response) throws Exception {
//                        mTextView.setText(response.toString());
//                    }
//                }, new Consumer<Throwable>() {
//                    @Override
//                    public void accept(Throwable throwable) throws Exception {
//                        mTextView.setText(throwable.getMessage());
//                    }
//                });
//        MovieService movieService = RetrofitManager.getInstance().create(MovieService.class);
//        Observable<MyBean> observable = movieService.getAccountBy(loginRequestMap("8833145829A4"));
//        observable.subscribeOn(Schedulers.io())
//                .observeOn(AndroidSchedulers.mainThread())
//                .subscribe(new Consumer<MyBean>() {
//                    @Override
//                    public void accept(MyBean bean) throws Exception {
//                        System.out.println(bean.toString());
//                    }
//                });
        MovieService movieService = RetrofitManager.getInstance().create(MovieService.class);
        Observable<TestBean> observable = movieService.test();
        observable.subscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Consumer<TestBean>() {
                    @Override
                    public void accept(TestBean testBean) throws Exception {
                        List<TestBean.DATABean> dataBeans = testBean.getDA_TA();
                        for (TestBean.DATABean dataBean : dataBeans) {
                            System.out.println("ID: " + dataBean.getID() + ", " +
                                    "LIN_K: " + dataBean.getLIN_K() + ", " +
                                    "N_AME: " + dataBean.getN_AME() + ", " +
                                    "VISIB_LE: " + dataBean.getVISIB_LE() + ", ");
                        }
                        System.out.println(testBean.getER_RORCO_DE() + ", " + testBean.getERRORM_SG());
//                        testJson(string);
                    }
                });
    }

    private void testJson(String json) {
        String regex = "(\\{|\\,)[a-zA-Z0-9_]+:";
//        String regex = "(\\{|\\,)[a-zA-Z0-9]+:";
        Pattern pattern = Pattern.compile(regex);
        StringBuffer sb = new StringBuffer();
        // 方法二：正则替换
        Matcher m = pattern.matcher(json);
        while (m.find()) {
            m.appendReplacement(sb, m.group().toLowerCase());
        }
        m.appendTail(sb);
        String msg = sb.toString();
        System.out.println(msg);
    }

    public static HashMap<String, String> loginRequestMap(String blueMacAddress) {
        HashMap<String, String> hashMap = new HashMap<>();
        hashMap.clear();
        hashMap.put("companyid", "101");
        hashMap.put("mac", blueMacAddress);//本处获取的是蓝牙的mac地址
        StringBuffer sb = new StringBuffer();
        sb.append("companyid=").append("101").append("&mac=").append(hashMap.get("mac"));
        sb = new StringBuffer(getMd5(sb.toString()));
        sb.append("123456");
        hashMap.put("digest", getMd5(sb.toString()));
        return hashMap;
    }

    /**
     * Gets md 5.
     *
     * @param plainText the plain text
     * @return the md 5
     */
    public static String getMd5(String plainText) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte b[] = md.digest();

            int i;

            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            //32位加密
            return buf.toString();
            // 16位的加密
            //return buf.toString().substring(8, 24);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return null;
        }

    }
}
